using System;
using System.Collections;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;
using CILDiffLib;

namespace CILDiff
{
    class CompareRevisions
    {
        private string GetFileThatExists(string path, string[] hints)
        {
            DirectoryInfo di = new DirectoryInfo(path);
            foreach (string hint in hints)
            {
                if (File.Exists(Path.Combine(path,hint)))
                {
                    return Path.Combine(path, hint);
                }
            }
            return null;
        }
        // Read folders, or from PySDB database (list of assemblies).
        private ArrayList GetAssemblies(string baseDir, string[] hints)
        {
            ArrayList assemList = new ArrayList();
            DirectoryInfo di = new DirectoryInfo(baseDir);
            ArrayList directories = new ArrayList();
            directories.AddRange(di.GetDirectories());
            directories.Sort( new DirectorySort() );
            foreach( DirectoryInfo dir in directories )
            {
                string assemb = GetFileThatExists(dir.FullName, hints);
                if (assemb != null)
                {
                    assemList.Add(assemb);
                }
            }
            return assemList;
        }
        public class DirectorySort : IComparer
        {
            int IComparer.Compare(object x, object y)
            {
                DirectoryInfo dirX = (DirectoryInfo)x;
                DirectoryInfo dirY = (DirectoryInfo)y;
                try
                {
                    return int.Parse(dirX.Name).CompareTo(int.Parse(dirY.Name));
                }
                catch (FormatException)
                {
                    return -1;
                }
            }
        }
        public class NaturalSort : IComparer
        {
            public int NaturalCompare(string strA, string strB)
            {
                ArrayList list = new ArrayList();
                ArrayList list2 = new ArrayList();
                foreach (Match mx in Regex.Matches(strA, @"(\d+|\D+)"))
                {
                    list.Add(mx.Groups[0].Value);
                }

                foreach (Match mx in Regex.Matches(strB, @"(\d+|\D+)"))
                {
                    list2.Add(mx.Groups[0].Value);
                }

                list = GetIntList(list);
                list2 = GetIntList(list2);
                for (int i = 0; i < list.Count; i++)
                {
                    IComparable x = list[i] as IComparable;
                    IComparable y = list2[i] as IComparable;
                    if (x.CompareTo(y) != 0)
                    {
                        return x.CompareTo(y);
                    }
                }
                return 0;
            }

            public ArrayList GetIntList(ArrayList list)
            {
                ArrayList newList = new ArrayList();
                for (int i = 0; i < list.Count; i++)
                {
                    object x = list[i];
                    try { newList.Add(int.Parse(x.ToString())); }
                    catch { newList.Add(x); }
                }
                return newList;
            }
            int IComparer.Compare(object x, object y)
            {
                return NaturalCompare(x.ToString(), y.ToString());
            }
        }

        public EntityVocabularyActivity CompareRevs(string baseDir, string[] hints)
        {
            ArrayList assembList = GetAssemblies(baseDir, hints);
            EntityVocabularyActivity activity = new EntityVocabularyActivity();
            for (int i = 0; i < assembList.Count - 1; i++)
            {
                Console.WriteLine("Version "+i +"->"+(i+1));
                //CILDiffLibPrime.Visit visit = new CILDiffLibPrime.Visit();
                CILDiffLib.Visit visit = new CILDiffLib.Visit();
                visit.CompareFiles((string)assembList[i], (string)assembList[i+1]);
                activity.EntityActivity.Add(visit.Topics);
                activity.MethodVocabulary.Add(visit.MethodTopics);
            }
            return activity;
        }
    }
}
